home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / progjour / 1991 / 02 / block.asm < prev    next >
Assembly Source File  |  1990-10-31  |  16KB  |  754 lines

  1.     title    block storage manager
  2.     include    asm.inc
  3.  
  4.     public    block_alloc
  5.     public    block_file_open
  6.     public    block_file_read
  7.     public    block_free
  8.     public    block_read
  9.  
  10. BLOCK_MAX        equ    512
  11. FIRST_BLOCK        equ    08000h    ; block handles start at 0x8000
  12.  
  13. NULL_BLOCK        equ    0
  14. NULL_EMS        equ    0
  15. NULL_ID            equ    0
  16. NULL_SWAP        equ    0
  17.  
  18. OPEN_LINK        equ    0FFFFh
  19.  
  20. block_str struc
  21.   blk_forward        dw  ?    ; forward link for LRU
  22.   blk_backward        dw  ?    ; backward link
  23.   blk_pointer        dd  ?    ; RAM address (or 0 if in EMS or DISK)
  24.   blk_ems_index        dw  ?    ; EMS index
  25.   blk_swap_index    dw  ?    ; swap file index (0 if not swapped)
  26.   blk_file_id        dw  ?    ; file identification (0 if not in file)
  27.   blk_file_index    dw  ?    ; file block index
  28.   blk_file_link        dw  ?    ; blocks for each file form a list
  29.   blk_byte_count    dw  ?    ; (file blocks may be less than 16k)
  30. block_str ends            ; (structure must be even number of bytes)
  31.  
  32.  
  33. XIB    segment word public 'DATA'    ; initialize block manager
  34. XIB    ends
  35. XI    segment word public 'DATA'
  36.     dw    block_preset
  37. XI    ends
  38. XIE    segment word public 'DATA'
  39. XIE    ends
  40.  
  41.  
  42.     .const
  43. ertx_block_handle    db    'Bad block handle',0
  44. ertx_empty_file        db    'Cannot map empty file',0
  45. ertx_free_block        db    'Cannot free block',0
  46. ertx_past_eof        db    'Block read past EOF',0
  47. ertx_virtual_full    db    'Virtual memory full',0
  48.  
  49.  
  50.     .data?
  51. block_table    dd    ?    ; array of block structures
  52.  
  53. ram_front    dw    ?    ; LRU list of RAM blocks
  54. ram_back    dw    ?
  55.  
  56. ems_front    dw    ?    ; LRU list of EMS blocks
  57. ems_back    dw    ?
  58.  
  59. free_front    dw    ?    ; free handle stack
  60. free_count    dw    ?    ; number of free blocks
  61.  
  62. file_blocks    dw    ?    ; # of blocks in file (see block_file_open)
  63.  
  64.     .code
  65.  extn abort_if_cf,calloc,clear_strerror,ems_exchange,ems_in,swap_in
  66.  extn ems_out,free,malloc,save_most,set_strerror,swap_out,check_block_file
  67.  extn open_block_file,read_block_file,set_block_handle
  68.  
  69.     page
  70. ;;    access block table
  71. ;
  72. ;    entry    BX    block handle
  73. ;    exit    DS:SI    block table entry for handle
  74. ;        Cf    if bad handle
  75. ;    uses    AX
  76. ;
  77. access_block_table proc
  78.     mov    ax,bx
  79.     sub    ax,FIRST_BLOCK
  80.     jb    abt1            ; if bad handle
  81.     cmp    ax,BLOCK_MAX
  82.     jae    abt1            ; if bad handle
  83.     mov    si,dx
  84.     mov    dx,size block_str
  85.     mul    dx
  86.     mov    dx,si
  87.  
  88.     lds    si,block_table[bp]
  89.     add    si,ax
  90.     ret
  91.  
  92. abt1:    lea    ax,ertx_block_handle    ; *Bad block handle*
  93.     jmp    set_strerror
  94. access_block_table endp
  95.  
  96.  
  97. ;;    block alloc
  98. ;
  99. ;    exit    AX    block size in bytes
  100. ;        BX    block handle
  101. ;        ES:DI    block pointer
  102. ;        Cf    if no memory
  103. ;
  104. block_alloc proc
  105.     pushm    si,ds
  106.     call    malloc_storage_block
  107.     jc    bal2            ;  if no memory
  108.  
  109.     call    new_block_handle
  110.     jc    bal1            ;  if no more block handles
  111.     mov    wptr blk_pointer[si],di
  112.     mov    wptr blk_pointer[si+2],es
  113.  
  114.     call    set_mru_ram        ; set most recently used
  115.     mov    ax,BLOCK_SIZE
  116.     mov    blk_byte_count[si],ax
  117.     clc
  118.     jmp    bal3
  119.  
  120. bal1:    call    free            ; here when out of handles, free
  121. bal2:    movx    bx,NULL_BLOCK        ;  storage and return error
  122.     stc
  123.  
  124. bal3:    popm    ds,si
  125.     ret
  126. block_alloc endp
  127.  
  128.  
  129. ;;    block file open
  130. ;
  131. ;    entry    DS:SI    file name
  132. ;    exit    AX    file size in blocks
  133. ;        BX    block handle
  134. ;        Cf    if file not found or empty
  135. ;
  136. block_file_open proc
  137.     pushm    cx,dx,di,si,ds
  138.     call    check_block_file
  139.     jnc    bfo4            ;  if existing file
  140.  
  141. bfo1:    call    open_block_file
  142.     jc    bfo4            ;  if file not found
  143.     jcxz    bfo7            ;  if empty file
  144.  
  145.     cmp    cx,free_count[bp]
  146.     ja    bfo5            ;  if not enough blocks for file
  147.  
  148.     mov    file_blocks[bp],cx
  149.     movx    cx,0
  150.  
  151.     call    new_file_block        ; allocate first file block
  152.     jc    bfo4
  153.     mov    bx,ax
  154.     cmp    cx,file_blocks[bp]
  155.     je    bfo3            ;  if file size <= 16k
  156.  
  157. bfo2:    mov    di,si
  158.     call    new_file_block
  159.     jc    bfo4
  160.     mov    blk_file_link[di],si
  161.     cmp    cx,file_blocks[bp]
  162.     jb    bfo2
  163.  
  164.     call    set_block_handle    ; save handle in case we open again
  165.  
  166. bfo3:    mov    ax,file_blocks[bp]    ; return file size (Cf unchanged)
  167.  
  168. bfo4:    popm    ds,si,di,dx,cx
  169.     ret
  170.  
  171. bfo5:    lea    ax,ertx_virtual_full    ; *Virtual memory full*
  172. bfo6:    call    set_strerror
  173.     jmp    bfo4
  174. bfo7:    lea    ax,ertx_empty_file    ; *Cannot map empty file*
  175.     jmp    bfo6
  176. block_file_open endp
  177.  
  178.  
  179. ;;    block file read
  180. ;
  181. ;    entry    AX    16k file block number (0..n)
  182. ;        BX    block index
  183. ;    exit    DS:SI    block pointer
  184. ;        AX    block size (<16k if last block)
  185. ;        Cf    if bad block index or past end of file
  186. ;
  187. block_file_read proc
  188.     push    cx
  189.     mov    cx,ax
  190.     call    access_block_table
  191.     jc    bfr4
  192.  
  193.     jcxz    bfr2            ;  if first block
  194. bfr1:    mov    si,blk_file_link[si]    ;  else chase linked list to
  195.     cmp    si,OPEN_LINK        ;    selected blk
  196.     loopne    bfr1
  197.     je    bfr3            ;  if block number too large
  198.  
  199. bfr2:    pop    cx
  200.     jmp    block_read_primitive
  201.  
  202. bfr3:    lea    ax,ertx_past_eof    ; *Block read past EOF*
  203.     call    set_strerror
  204. bfr4:    pop    cx
  205.     ret
  206. block_file_read endp
  207.  
  208.  
  209. ;;    block free
  210. ;
  211. ;    entry    BX    block index
  212. ;    exit    Cf    if bad index (cannot free file blocks)
  213. ;    uses    AX,BX
  214. ;
  215. block_free proc
  216.     pushm    di,si,ds,es
  217.     call    access_block_table
  218.     jc    bfe5
  219.  
  220.     cmp    blk_file_id[si],NULL_ID    ; illegal to free a file block
  221.     jne    bfe6            ;  if file block
  222.  
  223.     les    di,blk_pointer[si]
  224.     mov    ax,es
  225.     or    ax,di
  226.     jz    bfe1            ;  if not in RAM
  227.  
  228.     call    unlink_ram_list        ; unlink block from RAM LRU list
  229.     call    free            ; free storage
  230.     jmp    bfe3
  231.  
  232. bfe1:    mov    ax,blk_ems_index[si]
  233.     cmpx    ax,NULL_EMS
  234.     je    bfe2            ;  if not in EMS
  235.  
  236.     call    ems_in            ; free EMS block (ES:DI==NULL)
  237.     call    unlink_ems_list        ; unlink block from EMS LRU list
  238.     jmp    bfe3
  239.  
  240. bfe2:    mov    ax,blk_swap_index[si]
  241.     cmpx    ax,NULL_SWAP
  242.     je    bfe6            ;  if not in swap file (thus error)
  243.  
  244.     call    swap_in            ; free swap block (ES:DI==NULL)
  245.  
  246. bfe3:    mov    bx,size block_str    ; clear block table entry and
  247. bfe4:    dec    bx            ;  leave BX==0
  248.     dec    bx
  249.     mov    wptr [si+bx],ZER0
  250.     jnz    bfe4
  251.  
  252.     mov    ax,si            ; link onto free block stack
  253.     xchg    ax,free_front[bp]
  254.     mov    blk_backward[si],ax
  255.     inc    free_count[bp]
  256.  
  257.     clc
  258. bfe5:    popm    es,ds,si,di        ; (POP xS could fault in protect mode)
  259.     ret
  260.  
  261. bfe6:    lea    ax,ertx_free_block    ; *Cannot free block*
  262.     call    set_strerror
  263.     jmp    bfe5
  264. block_free endp
  265.  
  266.  
  267. ;;    block preset
  268. ;
  269. ;    uses    AX
  270. ;
  271. block_preset proc
  272.     call    save_most        ; allocate block table
  273.     mov    cx,BLOCK_MAX*size block_str
  274.     call    calloc            ;  (must have NULL offset)
  275.     call    abort_if_cf
  276.     mov    wptr block_table[bp],di
  277.     mov    wptr block_table[bp+2],es
  278.  
  279.     mov    ax,OPEN_LINK        ; build free list
  280.     mov    cx,BLOCK_MAX
  281.     mov    free_count[bp],cx
  282.     lds    si,block_table[bp]
  283.     mov    free_front[bp],si
  284. bps1:    lea    dx,[si+size block_str]
  285.     mov    blk_backward[si],dx
  286.     mov    blk_forward[si],ax
  287.     mov    blk_file_link[si],ax
  288.     xchg    dx,si
  289.     loop    bps1
  290.     mov    blk_backward[si-size block_str],ax
  291.  
  292.     mov    ram_front[bp],ax    ;\initialize LRU lists for RAM and EMS
  293.     mov    ram_back[bp],ax
  294.     mov    ems_front[bp],ax
  295.     mov    ems_back[bp],ax
  296.     ret
  297. block_preset endp
  298.  
  299.  
  300. ;;    block read
  301. ;
  302. ;    entry    BX    block index
  303. ;    exit    AX    block size
  304. ;        DS:SI    block pointer
  305. ;        Cf    if bad block or no memory
  306. ;
  307. block_read proc
  308.     call    access_block_table
  309.     jnc    block_read_primitive    ;\
  310.     ret                ;\
  311. block_read endp
  312.  
  313.  
  314. ;;    block read primitive
  315. ;
  316. ;    entry    DS:SI    block table pointer
  317. ;    exit    AX    block size
  318. ;        DS:SI    block pointer
  319. ;        Cf    if bad block or no memory
  320. ;
  321. block_read_primitive proc
  322.     pushm    di,es
  323.     cmp    wptr blk_pointer[si+2],NULL_POINTER
  324.     je    brp1            ;  if block is not in RAM
  325.     call    reset_mru_ram        ; move to front of LRU list
  326.     jmp    brp5
  327.  
  328. brp1:    call    malloc_storage_block    ; allocate storage for block
  329.     jc    brp6            ;  if no memory
  330.  
  331.     mov    ax,blk_ems_index[si]    ; check if block swapped to EMS
  332.     cmpx    ax,NULL_EMS
  333.     je    brp2            ;  if not in EMS
  334.  
  335.     call    ems_in            ;  else swap block in from EMS
  336.     jc    brp8            ;   if unexpected EMS error
  337.  
  338.     call    unlink_ems_list        ; delete from EMS LRU list
  339.     mov    blk_ems_index[si],NULL_EMS
  340.     jmp    brp4
  341.  
  342. brp2:    cmp    blk_file_id[si],NULL_ID    ; check if file block
  343.     je    brp3            ;  if not
  344.  
  345.     push    bx            ;  else read block from file
  346.     mov    bx,blk_file_id[si]
  347.     mov    ax,blk_file_index[si]
  348.     call    read_block_file
  349.     pop    bx
  350.     jc    brp8            ;  if error reading file
  351.     mov    blk_byte_count[si],ax
  352.     jmp    brp4            ;  else read OK
  353.  
  354. brp3:    mov    ax,blk_swap_index[si]    ; check if block swapped out
  355.     cmpx    ax,NULL_SWAP
  356.     je    brp7            ;  if not swapped - bad block handle
  357.     call    swap_in
  358.     jc    brp8            ;  if error swapping block in
  359.     mov    blk_swap_index[si],NULL_SWAP
  360.  
  361. brp4:    mov    wptr blk_pointer[si],di    ; save RAM pointer in block table
  362.     mov    wptr blk_pointer[si+2],es
  363.     call    set_mru_ram        ; move to front of LRU list
  364.  
  365. brp5:    mov    ax,blk_byte_count[si]    ; return RAM pointer and byte count
  366.     lds    si,blk_pointer[si]
  367.     clc
  368. brp6:    popm    es,di
  369.     ret
  370.  
  371. brp7:    lea    ax,ertx_block_handle    ; *Bad block handle*
  372.     call    set_strerror
  373.  
  374. brp8:    call    free
  375.     stc
  376.     jmp    brp6
  377. block_read_primitive endp
  378.  
  379.  
  380. ;;    free ram block
  381. ;
  382. ;    exit    Cf    if no RAM free
  383. ;    uses    AX
  384. ;
  385. free_ram_block proc
  386.     call    save_most
  387.     call    get_lru_ram        ; get least recently used memory block
  388.     jc    frb4            ;  if no blocks on LRU list
  389.  
  390.     les    di,blk_pointer[si]    ; else file block, swap to EMS
  391.     call    ems_out
  392.     jc    frb2            ;  if unable to swap to EMS
  393.     mov    blk_ems_index[si],ax    ;  else save EMS page index
  394.     call    set_mru_ems
  395.  
  396. frb1:    call    free            ; free storage
  397.     jc    frb4            ;  if unexpected error
  398.     mov    wptr blk_pointer[si],di    ;  (free returns with ES:DI==NULL)
  399.     mov    wptr blk_pointer[si+2],es
  400.     jmp    frb4
  401.  
  402. frb2:    call    clear_strerror        ; here when EMS is full
  403.     cmp    blk_file_id[si],NULL_ID    ; is block file or storage?
  404.     jne    frb1            ;  if file block - just free its ram
  405.  
  406.     mov    bx,si            ; try exchanging RAM block & LRU EMS
  407.     call    get_lru_ems
  408.     jc    frb3            ;  if no EMS (SI still -> RAM block)
  409.     mov    ax,blk_ems_index[si]
  410.     call    ems_exchange        ;  (ES:DI still points to RAM block)
  411.     jc    frb4            ;  if exchange failed (serious error)
  412.  
  413.     movx    ax,NULL_EMS        ; exchange EMS index and RAM pointers
  414.     xchg    ax,blk_ems_index[si]    ;  for exchanged blocks
  415.     mov    blk_ems_index[bx],ax
  416.     mov    wptr blk_pointer[bx],NULL_POINTER
  417.     mov    wptr blk_pointer[bx+2],NULL_POINTER
  418.     mov    wptr blk_pointer[si],di
  419.     mov    wptr blk_pointer[si+2],es
  420.  
  421.     xchg    bx,si            ; set most recently used EMS block
  422.     call    set_mru_ems
  423.     xchg    bx,si
  424.  
  425. frb3:    call    swap_out        ; write block to swap file
  426.     mov    blk_swap_index[si],ax    ;  set swap index (or 0 if failure)
  427.     jnc    frb1            ;  if swapped OK
  428.  
  429.     call    set_lru_ram        ; swap failed, re-link RAM block
  430.     movx    bx,NULL_BLOCK
  431.     stc
  432.  
  433. frb4:    ret
  434. free_ram_block endp
  435.  
  436.  
  437. ;;    get lru ems
  438. ;
  439. ;    exit    DS:SI    least recently used block in EMS
  440. ;        Cf    if no blocks in EMS (SI unchanged)
  441. ;    uses    AX
  442. ;
  443. get_lru_ems proc
  444.     mov    ax,OPEN_LINK
  445.     cmp    ax,ems_back[bp]
  446.     je    gle2            ;\ if no EMS blocks
  447.  
  448.     lds    si,block_table[bp]
  449.     mov    si,ems_back[bp]
  450.     cmp    si,ems_front[bp]
  451.     je    gle1            ;  if only one EMS block
  452.  
  453.     push    bx
  454.     mov    bx,blk_forward[si]
  455.     mov    blk_backward[bx],ax
  456.     mov    ems_back[bp],bx
  457.     pop    bx
  458.     clc
  459.     ret
  460.  
  461. gle1:    mov    ems_front[bp],ax
  462.     mov    ems_back[bp],ax
  463.     ret                ;  (Cf==0)
  464.  
  465. gle2:    stc
  466.     ret
  467. get_lru_ems endp
  468.  
  469.  
  470. ;;    get lru ram
  471. ;
  472. ;    exit    DS:SI    least recently used block in RAM
  473. ;        Cf    if no unlocked blocks in RAM
  474. ;    uses    AX
  475. ;
  476. get_lru_ram proc
  477.     mov    ax,OPEN_LINK
  478.     lds    si,block_table[bp]
  479.     mov    si,ram_back[bp]
  480.     cmp    si,ax
  481.     je    glr2            ;  if no RAM blocks
  482.     cmp    si,ram_front[bp]
  483.     je    glr1            ;  if only one RAM block
  484.  
  485.     push    bx
  486.     mov    bx,blk_forward[si]
  487.     mov    blk_backward[bx],ax
  488.     mov    ram_back[bp],bx
  489.     pop    bx
  490.     clc
  491.     ret
  492.  
  493. glr1:    mov    ram_front[bp],ax
  494.     mov    ram_back[bp],ax
  495.     ret                ;  (Cf==0)
  496.  
  497. glr2:    stc
  498.     ret
  499. get_lru_ram endp
  500.  
  501.  
  502. ;;    malloc storage block
  503. ;
  504. ;    exit    ES:DI    storage block
  505. ;        Cf    if unable to allocate storage
  506. ;    uses    AX
  507. ;
  508. malloc_storage_block proc
  509.     push    cx
  510.     mov    cx,BLOCK_SIZE        ; allocate block of memory
  511.     call    malloc
  512.     jnc    msb1            ;  if OK
  513.  
  514.     call    clear_strerror        ; clear malloc error
  515.     call    free_ram_block        ; swap to EMS or disk to free ram
  516.     jc    msb1            ;  if too many locked blocks
  517.  
  518.     call    malloc            ; try malloc one more time
  519.  
  520. msb1:    pop    cx
  521.     ret
  522. malloc_storage_block endp
  523.  
  524.  
  525. ;;    new block handle
  526. ;
  527. ;    exit    BX    block handle
  528. ;        DS:SI    block table entry
  529. ;        Cf    if no free handles
  530. ;    uses    AX
  531. ;
  532. new_block_handle proc
  533.     lds    si,block_table[bp]    ; get first block from free list
  534.     mov    si,free_front[bp]
  535.     cmp    si,OPEN_LINK
  536.     je    nbh1            ;  if no more handles
  537.     mov    ax,blk_backward[si]
  538.     mov    free_front[bp],ax
  539.     dec    free_count[bp]
  540.  
  541.     push    dx            ; compute handle from table offset
  542.     mov    ax,si
  543.     movx    dx,0
  544.     mov    bx,size block_str
  545.     div    bx
  546.     add    ax,FIRST_BLOCK
  547.     mov    bx,ax
  548.     pop    dx
  549.     ret
  550.  
  551. nbh1:    lea    ax,ertx_virtual_full    ; *Virtual memory full*
  552.     jmp    set_strerror
  553. new_block_handle endp
  554.  
  555.  
  556. ;;    new file block
  557. ;
  558. ;    entry    CX    block number
  559. ;        DX    file id
  560. ;    exit    AX    block handle
  561. ;        CX    +1
  562. ;        DS:SI    block table entry
  563. ;        Cf    if no more blocks
  564. ;
  565. new_file_block proc
  566.     push    bx
  567.     call    new_block_handle    ; allocate block
  568.     jc    nfb1            ;  if no more blocks
  569.  
  570.     mov    blk_file_id[si],dx    ; set file id and block number
  571.     mov    blk_file_index[si],cx
  572.     inc    cx
  573.  
  574.     mov    ax,OPEN_LINK        ; reset links
  575.     mov    blk_file_link[si],ax
  576.     mov    blk_forward[si],ax
  577.     mov    blk_backward[si],ax
  578.  
  579.     mov    ax,bx            ;\
  580. nfb1:    pop    bx
  581.     ret
  582. new_file_block endp
  583.  
  584.  
  585. ;;    reset mru ram
  586. ;
  587. ;    entry    DS:SI    most recently used table entry
  588. ;    uses    AX
  589. ;
  590. reset_mru_ram proc
  591.     cmp    si,ram_front[bp]
  592.     je    rmr4            ;  if already most recently used
  593.  
  594.     push    bx
  595.     cmp    si,ram_back[bp]
  596.     je    rmr1            ;  if least recently used
  597.  
  598.     mov    ax,blk_forward[si]    ; delete from middle of LRU list
  599.     mov    bx,blk_backward[si]
  600.     mov    blk_forward[bx],ax
  601.     xchg    ax,bx
  602.     mov    blk_backward[bx],ax
  603.     jmp    rmr2
  604.  
  605. rmr1:    call    get_lru_ram        ; delete from back of LRU list
  606.     jc    rmr3            ;  if internal error
  607. rmr2:    call    set_mru_ram
  608.     clc
  609. rmr3:    pop    bx
  610. rmr4:    ret
  611. reset_mru_ram endp
  612.  
  613.  
  614. ;;    set lru ram
  615. ;
  616. ;    entry    DS:SI    least recently used table entry
  617. ;    uses    AX,BX
  618. ;
  619. set_lru_ram proc
  620.     mov    ax,OPEN_LINK        ; check for empty list
  621.     mov    bx,si
  622.     xchg    bx,ram_back[bp]
  623.     cmp    bx,ax
  624.     je    slr1            ; if empty list
  625.  
  626.     mov    blk_backward[si],ax    ; else link onto back of list
  627.     mov    blk_forward[si],bx
  628.     mov    blk_backward[bx],si
  629.     ret
  630.  
  631. slr1:    mov    ram_front[bp],si    ; create list with one element
  632.     mov    blk_forward[si],ax
  633.     mov    blk_backward[si],ax
  634.     ret
  635. set_lru_ram endp
  636.  
  637.  
  638. ;;    set mru ems
  639. ;
  640. ;    entry    DS:SI    most recently used table entry
  641. ;    uses    AX
  642. ;
  643. set_mru_ems proc
  644.     push    bx
  645.     mov    ax,OPEN_LINK        ; check for empty list
  646.     mov    bx,si
  647.     xchg    bx,ems_front[bp]
  648.     cmp    bx,ax
  649.     je    sme1            ; if empty list
  650.  
  651.     mov    blk_forward[si],ax    ; else link onto front of list
  652.     mov    blk_backward[si],bx
  653.     mov    blk_forward[bx],si
  654.     pop    bx
  655.     ret
  656.  
  657. sme1:    mov    ems_back[bp],si        ; create list with one element
  658.     mov    blk_forward[si],ax
  659.     mov    blk_backward[si],ax
  660.     pop    bx
  661.     ret
  662. set_mru_ems endp
  663.  
  664.  
  665. ;;    set mru ram
  666. ;
  667. ;    entry    DS:SI    most recently used table entry
  668. ;    uses    AX
  669. ;
  670. set_mru_ram proc
  671.     push    bx
  672.     mov    ax,OPEN_LINK        ; check for empty list
  673.     mov    bx,si
  674.     xchg    bx,ram_front[bp]
  675.     cmp    bx,ax
  676.     je    smr1            ; if empty list
  677.  
  678.     mov    blk_forward[si],ax    ; else link onto front of list
  679.     mov    blk_backward[si],bx
  680.     mov    blk_forward[bx],si
  681.     pop    bx
  682.     ret
  683.  
  684. smr1:    mov    ram_back[bp],si        ; create list with one element
  685.     mov    blk_forward[si],ax
  686.     mov    blk_backward[si],ax
  687.     pop    bx
  688.     ret
  689. set_mru_ram endp
  690.  
  691.  
  692. ;;    unlink ems list
  693. ;
  694. ;    entry    DS:SI    block table entry
  695. ;    uses    AX
  696. ;
  697. unlink_ems_list proc
  698.     cmp    si,ems_back[bp]
  699.     je    uel1            ; if EMS block is LRU
  700.  
  701.     push    bx
  702.     cmp    si,ems_front[bp]
  703.     je    uel2            ; if EMS block is MRU
  704.  
  705.     mov    ax,blk_forward[si]    ; delete from middle of LRU list
  706.     mov    bx,blk_backward[si]
  707.     mov    blk_forward[bx],ax
  708.     xchg    ax,bx
  709.     mov    blk_backward[bx],ax
  710.     jmp    uel3
  711.  
  712. uel1:    jmp    get_lru_ems
  713.  
  714. uel2:    mov    bx,blk_backward[si]    ; delete from front of LRU list
  715.     mov    blk_forward[bx],OPEN_LINK
  716.     mov    ems_front[bp],bx
  717.  
  718. uel3:    pop    bx
  719.     ret
  720. unlink_ems_list endp
  721.  
  722.  
  723. ;;    unlink ram list
  724. ;
  725. ;    entry    DS:SI    block table entry
  726. ;    uses    AX
  727. ;
  728. unlink_ram_list proc
  729.     cmp    si,ram_back[bp]
  730.     je    url1            ; if RAM block is LRU
  731.  
  732.     push    bx
  733.     cmp    si,ram_front[bp]
  734.     je    url2            ; if RAM block is MRU
  735.  
  736.     mov    ax,blk_forward[si]    ; delete from middle of LRU list
  737.     mov    bx,blk_backward[si]
  738.     mov    blk_forward[bx],ax
  739.     xchg    ax,bx
  740.     mov    blk_backward[bx],ax
  741.     jmp    url3
  742.  
  743. url1:    jmp    get_lru_ram
  744.  
  745. url2:    mov    bx,blk_backward[si]    ; delete from front of LRU list
  746.     mov    blk_forward[bx],OPEN_LINK
  747.     mov    ram_front[bp],bx
  748.  
  749. url3:    pop    bx
  750.     ret
  751. unlink_ram_list endp
  752.  
  753.     end
  754.